﻿// ==================================================================================================
// Copyright(C) 2018 FI Ltd. All rights reserved.
//
// SYSTEM NAME	    : FI.Net Application Framework
// COMPONENT ID	    : FI.Core
// COMPONENT DESC   : The foundation component of the whole framework. 	
//
// CREATED DATE/BY  : 18 Aug 2018 / Tian Mi
//
// REVISION HISTORY :	
// DATE/BY			SR#/CS/PM#/OTHERS		DESCRIPTION OF CHANGE
// ==================================================================================================

using System;
using System.Configuration;
using System.Linq;
using FI.Core.Properties;
using FI.Core.IoC;
using FI.Core.Utilities;
using FI.Core.SettingSource;
using FI.Core.Configuration;

namespace FI.Core
{
    /// <summary>
    /// The static facade class to manangement configuration.
    /// </summary>
    public static class ConfigManager
    {
        /// <summary>
        /// Tries the get configuration section.
        /// </summary>
        /// <typeparam name="TConfigSection">The type of the config section.</typeparam>
        /// <param name="configSectionName">Name of the config section.</param>
        /// <param name="configurationSection">The configuration section.</param>
        /// <returns>A <see cref="bool"/> value indicating whether to successfully get the <see cref="ConfigurationSection"/>.</returns>
        public static bool TryGetConfigurationSection<TConfigSection>(string configSectionName, out TConfigSection configurationSection) where TConfigSection : ConfigurationSection
        {
            Guard.ArgumentNotNullOrEmpty(configSectionName, "configSectionName");
            configurationSection = SettingSourceFactory.GetSettingSource().GetConfigurationSection(configSectionName) as TConfigSection;
            return configurationSection != null;
        }

        /// <summary>
        /// Tries the get configuration section.
        /// </summary>
        /// <typeparam name="TConfigSection">The type of the config section.</typeparam>
        /// <param name="configurationSection">The configuration section.</param>
        /// <returns>A <see cref="bool"/> value indicating whether to successfully get the <see cref="ConfigurationSection"/>.</returns>
        public static bool TryGetConfigurationSection<TConfigSection>(out TConfigSection configurationSection) where TConfigSection : ConfigurationSection
        {
            ConfigurationSectionNameAttribute attribute = AttributeAccessor.GetAttributes<ConfigurationSectionNameAttribute>(typeof(TConfigSection), false).FirstOrDefault();
            if (null == attribute)
            { 
                throw new InvalidOperationException(Resources.ExceptionConfigurationSectionNameAttributeNotExists.Format(new object[]{ typeof(ConfigurationSectionNameAttribute).Name}));
            }
            return TryGetConfigurationSection(attribute.SectionName, out configurationSection);
        }

        /// <summary>
        /// Gets the configuration section.
        /// </summary>
        /// <typeparam name="TConfigSection">The type of the config section.</typeparam>
        /// <param name="configSectionName">Name of the config section.</param>
        /// <returns>The located <see cref="ConfigurationSection"/>.</returns>
        public static TConfigSection GetConfigurationSection<TConfigSection>(string configSectionName) where TConfigSection : ConfigurationSection
        {          
            Guard.ArgumentNotNullOrEmpty(configSectionName,"configSectionName");
            var configSection = SettingSourceFactory.GetSettingSource().GetConfigurationSection(configSectionName) as TConfigSection;
            if (null == configSection)
            {
                throw new ConfigurationErrorsException(ResourceUtility.Format(Resources.ExceptionMissingConfigSection, configSectionName));
            }

            TConfigSection configurationSection = configSection as TConfigSection;
            if (null == configurationSection)
            {
                throw new InvalidCastException(ResourceUtility.Format(Resources.ExceptionNotSpeciifedConfigSection, configSectionName, typeof(TConfigSection).FullName));
            }

            return configurationSection;            
        }

        /// <summary>
        /// Gets the configuration section.
        /// </summary>
        /// <typeparam name="TConfigSection">The type of the config section.</typeparam>
        /// <returns>The located <see cref="ConfigurationSection"/>.</returns>
        public static TConfigSection GetConfigurationSection<TConfigSection>() where TConfigSection : ConfigurationSection
        {
            ConfigurationSectionNameAttribute attribute = AttributeAccessor.GetAttributes<ConfigurationSectionNameAttribute>(typeof(TConfigSection), false).FirstOrDefault();
            if (null == attribute)
            {
                throw new InvalidOperationException(Resources.ExceptionConfigurationSectionNameAttributeNotExists.Format(new object[] { typeof(ConfigurationSectionNameAttribute).Name }));
            }
            return GetConfigurationSection<TConfigSection>(attribute.SectionName);
        }

        /// <summary>
        /// Gets the connection strings settings.
        /// </summary>
        /// <value>The connection strings settings.</value>
        public static  ConnectionStringSettingsCollection ConnectionStrings
        {
            get
            {
                return ConfigManager.GetConfigurationSection<ConnectionStringsSection>("connectionStrings").ConnectionStrings;
            }
        }
    }
}
